package com.night.icm.service.business.service;

import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.night.icm.common.jpa.PageHelper;
import com.night.icm.common.service.PageDataUtil;
import com.night.icm.common.utils.PageDataDTO;
import com.night.icm.common.utils.TermType;
import com.night.icm.model.business.StudentCourseGradeGatherDTO;
import com.night.icm.persistence.business.entity.StudentCourseGrade;
import com.night.icm.persistence.business.entity.StudentCourseGradeGather;
import com.night.icm.persistence.business.reporsitory.StudentCourseGradeGatherRepository;
import com.night.icm.persistence.business.reporsitory.StudentCourseGradeRepository;
import com.night.icm.service.business.mapper.StudentCourseGradeGatherMapper;
import com.night.icm.service.business.mapper.StudentCourseGradeMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * StudentCourseGradeGatherServiceImpl
 *
 * @author Liao ZhiYong
 * @date 2020/2/16
 */
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class StudentCourseGradeGatherServiceImpl implements StudentCourseGradeGatherService {

    private final StudentCourseGradeGatherRepository studentCourseGradeGatherRepository;
    private final StudentCourseGradeGatherMapper studentCourseGradeGatherMapper;
    private final StudentCourseGradeRepository studentCourseGradeRepository;
    private final StudentCourseGradeMapper studentCourseGradeMapper;

    @Autowired
    public StudentCourseGradeGatherServiceImpl(StudentCourseGradeGatherRepository studentCourseGradeGatherRepository, StudentCourseGradeGatherMapper studentCourseGradeGatherMapper, StudentCourseGradeRepository studentCourseGradeRepository, StudentCourseGradeMapper studentCourseGradeMapper) {
        this.studentCourseGradeGatherRepository = studentCourseGradeGatherRepository;
        this.studentCourseGradeGatherMapper = studentCourseGradeGatherMapper;
        this.studentCourseGradeRepository = studentCourseGradeRepository;
        this.studentCourseGradeMapper = studentCourseGradeMapper;
    }

    /**
     * 分页查询学生课程成绩汇总
     *
     * @param page      页号，从0开始
     * @param size      每页记录条数
     * @param sort      排序字段，例如：字段1,asc,字段2,desc
     * @param studentId 学生id
     * @param year      所属年度
     * @param termType  所属学期
     * @return 学生课程成绩汇总
     */
    @Override
    public PageDataDTO<StudentCourseGradeGatherDTO> findOnePage(int page, int size, String sort, String studentId, String year, TermType termType) {
        Specification<StudentCourseGradeGather> specification = this.getSpecification(studentId, year, termType);
        Page<StudentCourseGradeGather> all = this.studentCourseGradeGatherRepository.findAll(specification, PageHelper.generatePageRequest(page, size, sort));
        List<StudentCourseGradeGatherDTO> dtos = this.studentCourseGradeGatherMapper.toList(all.getContent());
        return PageDataUtil.toPageData(all, dtos);
    }

    /**
     * 模糊查询学生课程成绩汇总
     *
     * @param studentCode 学生学号
     * @param year      所属年度
     * @param termType  所属学期
     * @return 学生课程成绩汇总
     */
    @Override
    public List<StudentCourseGradeGatherDTO> search(String studentCode, String year, TermType termType) {
        Specification<StudentCourseGradeGather> specification = this.getSpecification(studentCode, year, termType);
        List<StudentCourseGradeGather> all = this.studentCourseGradeGatherRepository.findAll(specification);
        List<StudentCourseGradeGatherDTO> gradeGathers = this.studentCourseGradeGatherMapper.toList(all);
        // 查找gradeGathers中所有的学生课程成绩
        for (StudentCourseGradeGatherDTO gather: gradeGathers
             ) {
            List<StudentCourseGrade> grades = this.studentCourseGradeRepository.findByStudentCourseGradeGatherId(Long.valueOf(gather.getId()));
            gather.setStudentCourseGrades(this.studentCourseGradeMapper.toList(grades));
        }
        return gradeGathers;
    }

    /**
     * 获得specification
     *
     * @param studentCode 学生code
     * @param year      所属年度
     * @param termType  所属学期
     * @return specification
     */
    private Specification<StudentCourseGradeGather> getSpecification(String studentCode, String year, TermType termType) {
        Specification<StudentCourseGradeGather> specification = ((Root<StudentCourseGradeGather> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
            List<Predicate> conditions = new ArrayList<>();
            if (!StringUtils.isAllBlank(studentCode, year) || null != termType) {
                if (StringUtils.isNotBlank(studentCode)) {
                    conditions.add(cb.and(cb.equal(root.get("studentCode").as(String.class), Long.valueOf(studentCode))));
                }
                if (StringUtils.isNotBlank(year)) {
                    conditions.add(cb.and(cb.equal(root.get("year").as(Integer.class), Integer.valueOf(year))));
                }
                if (null != termType) {
                    conditions.add(cb.and(cb.equal(root.get("termType").as(TermType.class), termType)));
                }
            }
            if (!conditions.isEmpty()) {
                query.where(conditions.toArray(new Predicate[0]));
            }
            return null;
        });
        return specification;
    }
}